package com.jamal2362.apktool.task;

import android.content.Context;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.logging.Level;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import com.jamal2362.apktool.R;
import com.jamal2362.apktool.fragment.files.Refreshable;
import com.jamal2362.apktool.util.FileUtils;
import java.util.List;
import java.util.ArrayList;

public class UnzipTask extends AbstractTask {
	private Runnable callback;
	private Context context;
	private String target;
	private List<String> filter;

	public UnzipTask(Context ctx, Refreshable refresh, File target) {
		super(ctx, refresh);
		this.context = ctx;
		this.filter = new ArrayList<String>();
		this.target = target.getAbsolutePath();
		this.callback = null;
	}

	public UnzipTask(Context ctx, Refreshable refresh, File target, String ext) {
		super(ctx, refresh);
		this.context = ctx;
		this.filter = new ArrayList<String>();
		this.filter.add(ext);
		this.target = target.getAbsolutePath();
		this.callback = null;
	}

	public UnzipTask(Context ctx, Refreshable refresh, File target, String ext, Runnable callback) {
		super(ctx, refresh);
		this.context = ctx;
		this.filter = new ArrayList<String>();
		this.filter.add(ext);
		this.target = target.getAbsolutePath();
		this.callback = callback;
	}

	public UnzipTask(Context ctx, Refreshable refresh, File target, List<String> ext, Runnable callback) {
		super(ctx, refresh);
		this.context = ctx;
		this.filter = new ArrayList<String>();
		this.filter.addAll(ext);
		this.target = target.getAbsolutePath();
		this.callback = callback;
	}

	@Override
	protected boolean process(File f) {
		info(R.string.extraction, f.getAbsolutePath());
		try {
			extract(f);
			return true;
		} catch (Exception e) {
			log(Level.WARNING, e.getMessage(), e);
			return false;
		}
	}

	@Override
	protected boolean shouldShowFinishDialog() {
		return false;
	}

	@Override
	protected int getTitle() {
		return R.string.extract;
	}

	@Override
	protected void onPostExecute(Boolean result) {
		super.onPostExecute(result);
		if (result && callback != null)
			callback.run();
	}

	public void extract(File zipFile) throws Exception {
		int count = 0;
		byte[] buffer = new byte[2048];
        ZipFile zip = new ZipFile(zipFile);
        Enumeration e = zip.entries();
        while (e.hasMoreElements()) {
            ZipEntry entry = (ZipEntry) e.nextElement();
			createDirs(entry);
			if (entry.isDirectory())
				continue;
			if (!filter.isEmpty()) {
				boolean contains = filter.contains(entry.getName());
				if (!contains) {
					for (String filtr : filter) {
						contains = entry.getName().toLowerCase().endsWith(filtr.toLowerCase());
						if (contains)
							break;
					}
				}
				if (!contains)
					continue;
			}
            String[] sn = FileUtils.parseFileName(entry.getName());
			if (!sn[1].equals(""))
				sn[1] = "." + sn[1];
			String name = FileUtils.genName(context, target, sn[0], sn[1], 0);
			File file = new File(target + File.separator + name);
            InputStream is = zip.getInputStream(entry);
            FileOutputStream fos = new FileOutputStream(file);
            try {
				while ((count = is.read(buffer)) != -1)
					fos.write(buffer, 0, count);
			} finally {
				is.close();
				fos.close();
			}
        }
	}

	private void createDirs(ZipEntry entry) {
		int endSlash = entry.getName().lastIndexOf(File.separator);
		if (endSlash <= 0 && !entry.isDirectory())
			return;
		File subDir = new File(target + File.separator + entry.getName().substring(0, endSlash));
		if (!subDir.exists())
			subDir.mkdirs();
	}
}
